/**
 * Generali Solutions d'assurances - Tous droits réservés &copy; 2007 - 2010
 */
package fr.generali.accueilclient.client.assembler.input;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import fr.generali.accueilclient.client.om.IClientAssociation;
import fr.generali.accueilclient.client.om.IClientAutre;
import fr.generali.accueilclient.client.om.IClientCollectivite;
import fr.generali.accueilclient.client.om.IClientCopropriete;
import fr.generali.accueilclient.client.om.IClientEntreprise;
import fr.generali.accueilclient.client.om.IIndicateursDemat;
import fr.generali.accueilclient.client.om.IPersonneMorale;
import fr.generali.accueilclient.client.om.NaturePersonne;
import fr.generali.accueilclient.utils.constantes.CodeEtatPersonneEnum;
import fr.generali.accueilclient.utils.constantes.CodePopulationEnum;
import fr.generali.refservcommuns.clients.prima.DateRange;
import fr.generali.refservcommuns.clients.prima.DatedMonetaryQuantityRangeValue;
import fr.generali.refservcommuns.clients.prima.DatedQuantity;
import fr.generali.refservcommuns.clients.prima.DatedQuantityRangeValue;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoProcedureJudiciaire;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoResultatFinancierAExport;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoResultatFinancierFrance;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoSuiviAnnuelEntreprise;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.gestionrelationsaffaire.DtoRelationClient;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoAssociation;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoCoPropriete;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoCollectiviteLocale;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoEntreprise;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoExploitationAgricole;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoIndicateurDematerialisation;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoPersonneMorale;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoSecteurActivite;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoVisibilite;

/**
 * @author selrhazala
 */
@Component("personneMoraleToDtoPersonneMoraleConverter")
public class PersonneMoraleToDtoPersonneMoraleConverter implements Converter<IPersonneMorale, DtoPersonneMorale> {

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(PersonneMoraleToDtoPersonneMoraleConverter.class);

    /**
     * {@inheritDoc}
     */
    public DtoPersonneMorale convert(IPersonneMorale personneMorale) {
        // init date du jour
        XMLGregorianCalendar dateDuJour = null;
        try {
            GregorianCalendar gCalendar1 = new GregorianCalendar();
            gCalendar1.setTime(new Date());
            dateDuJour = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar1);
        } catch (DatatypeConfigurationException e) {
            LOGGER.debug("erreur datatype configuration");
        }

        return buildPersonneMorale(personneMorale, dateDuJour);
    }

    /**
     * @param personneMorale la personne morale
     * @param dateDuJour la date du jour
     * @return DtoPersonneMorale
     */
    public DtoPersonneMorale buildPersonneMorale(IPersonneMorale personneMorale, XMLGregorianCalendar dateDuJour) {

        // Critères de personne physique en commun pour les personnes morales
        DtoPersonneMorale dtoPersonneMorale = new DtoPersonneMorale();
        dtoPersonneMorale.setRaisonSociale(personneMorale.getRaisonSociale());
        dtoPersonneMorale.setNomCommercial(personneMorale.getRaisonSociale());
        dtoPersonneMorale.setCodeNAF(personneMorale.getCodeNaf());
        dtoPersonneMorale.setCompteEspaceClient(personneMorale.getCompteEspaceClient());
        dtoPersonneMorale.setDenominationFUE(personneMorale.getIdClientFue());
        dtoPersonneMorale.setNaturePersonne(personneMorale.getNaturePersonne().getValue());
        dtoPersonneMorale.setTypePersonneMorale(personneMorale.getNaturePersonne().getValue());
        dtoPersonneMorale.setFormeJuridique(personneMorale.getFormeJuridique());
        dtoPersonneMorale.setSigle(personneMorale.getSigle());
        dtoPersonneMorale.setVip(personneMorale.isClientVIP());
        dtoPersonneMorale.setRaisonConnaissanceTiers(personneMorale.getOrigineClient());
        dtoPersonneMorale.setDateDebutClient(dateDuJour);
        dtoPersonneMorale.setDateCreation(dateDuJour);
        dtoPersonneMorale.setEtat(CodeEtatPersonneEnum.CODE_ETAT_0.getCode());

        if (personneMorale.getDateDebut() != null) {
            try {
                GregorianCalendar gCalendar4 = new GregorianCalendar();
                gCalendar4.setTime(personneMorale.getDateDebut());
                XMLGregorianCalendar xmlCalendar4 = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar4);
                dtoPersonneMorale.setDateEtablissement(xmlCalendar4);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }
        }

        DtoProcedureJudiciaire dtoProcedureJudiciaire = new DtoProcedureJudiciaire();
        dtoProcedureJudiciaire.setTypeProcedureJudiciaire(personneMorale.getTypeProcedure());

        if (personneMorale.getDateJugement() != null) {
            try {
                GregorianCalendar gCalendar5 = new GregorianCalendar();
                gCalendar5.setTime(personneMorale.getDateJugement());
                XMLGregorianCalendar xmlCalendar5 = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar5);
                dtoProcedureJudiciaire.setDateJugement(xmlCalendar5);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }
        }

        List<DtoProcedureJudiciaire> listePJ = new ArrayList<DtoProcedureJudiciaire>();
        listePJ.add(dtoProcedureJudiciaire);
        dtoPersonneMorale.getProcedureJudiciaire().addAll(listePJ);

        DtoRelationClient dtoRelationClient = new DtoRelationClient();
        dtoRelationClient.setTitreCourrier(personneMorale.getTitreCourrier());
        dtoPersonneMorale.setRelationClient(dtoRelationClient);

        if (!NaturePersonne.ENTREPRISE.equals(personneMorale.getNaturePersonne())
                        && StringUtils.isNotEmpty(personneMorale.getAnneeExercice())) {
            DtoSuiviAnnuelEntreprise dtoSuiviAnnuelEntreprise = new DtoSuiviAnnuelEntreprise();
            dtoSuiviAnnuelEntreprise.setExercice(BigInteger.valueOf(Long.parseLong(personneMorale.getAnneeExercice())));
            List<DtoSuiviAnnuelEntreprise> listeSAE = new ArrayList<DtoSuiviAnnuelEntreprise>();
            listeSAE.add(dtoSuiviAnnuelEntreprise);
            dtoPersonneMorale.getSuiviAnnuelEntreprise().addAll(listeSAE);
        }

        DtoSecteurActivite dtoSecteurActivite = new DtoSecteurActivite();
        dtoSecteurActivite.setCode(personneMorale.getSecteurActivite());
        dtoPersonneMorale.setSecteurActivite(dtoSecteurActivite);

        DtoVisibilite dtoVisibilite = new DtoVisibilite();
        dtoVisibilite.setIdentifiantIntermediaire(personneMorale.getCodeIntermediaire());
        dtoVisibilite.setIdentifiantClientAgent(personneMorale.getNumeroClientAgent());
        dtoVisibilite.setIdentifiantPointVente(personneMorale.getPointDeVente());
        dtoVisibilite.setIdentifiantChargeClientele(personneMorale.getChargeClientele());
        dtoVisibilite.setCodePopulation(CodePopulationEnum.POPULATION_ACC.getCode());
        dtoPersonneMorale.setVisibilite(dtoVisibilite);

        if (StringUtils.isNotEmpty(personneMorale.getMoisClotureComptable())) {
            dtoPersonneMorale.setMoisClotureComptable(BigInteger.valueOf(Long.parseLong(personneMorale
                            .getMoisClotureComptable())));
        }

        if (NaturePersonne.ENTREPRISE.equals(personneMorale.getNaturePersonne())) {
            IClientEntreprise clientEntreprise = IClientEntreprise.class.cast(personneMorale);
            dtoPersonneMorale = buildEntreprise(dtoPersonneMorale, clientEntreprise);
        } else {
            if (NaturePersonne.COLLECTIVITE.equals(personneMorale.getNaturePersonne())) {
                IClientCollectivite clientCollectivite = IClientCollectivite.class.cast(personneMorale);
                dtoPersonneMorale = buildCollectivite(dtoPersonneMorale, clientCollectivite);
            } else {
                if (NaturePersonne.COPROPRIETE.equals(personneMorale.getNaturePersonne())) {
                    IClientCopropriete clientCopropriete = IClientCopropriete.class.cast(personneMorale);
                    dtoPersonneMorale = buildCopropriete(dtoPersonneMorale, clientCopropriete);
                } else {
                    if (NaturePersonne.ASSOCIATION.equals(personneMorale.getNaturePersonne())) {
                        IClientAssociation clientAssociation = IClientAssociation.class.cast(personneMorale);
                        dtoPersonneMorale = buildAssociation(dtoPersonneMorale, clientAssociation);
                    } else if (NaturePersonne.AUTRE.equals(personneMorale.getNaturePersonne())) {
                        IClientAutre clientAutre = IClientAutre.class.cast(personneMorale);
                        dtoPersonneMorale = buildAutre(dtoPersonneMorale, clientAutre);
                    }
                }
            }
        }

        if (personneMorale.getIndicateursDemat() != null) {

            Converter<IIndicateursDemat, List<DtoIndicateurDematerialisation>> converterIndDemat =
                            new IndicateursDemat2DtoIndicateurDematConverter();

            List<DtoIndicateurDematerialisation> listeDtoIndDemat =
                            converterIndDemat.convert(personneMorale.getIndicateursDemat());

            if (CollectionUtils.isNotEmpty(listeDtoIndDemat)) {
                dtoPersonneMorale.getInformationDematerialisation().addAll(listeDtoIndDemat);
            }
        }

        return dtoPersonneMorale;
    }

    /**
     * @param dtoPersonneMorale la personne morale
     * @param clientEntreprise l'entreprise
     * @return DtoPersonneMorale
     */
    public DtoPersonneMorale buildEntreprise(DtoPersonneMorale dtoPersonneMorale, IClientEntreprise clientEntreprise) {
        // Critères concernant uniquement l'entreprise

        // if (StringUtils.isNotEmpty(clientEntreprise.getAnneeExercice())) {
        List<DtoResultatFinancierFrance> resultatFinancier = new ArrayList<DtoResultatFinancierFrance>();
        DtoResultatFinancierFrance dtoResultatFinancierFrance = new DtoResultatFinancierFrance();
        DatedMonetaryQuantityRangeValue dmqrv = new DatedMonetaryQuantityRangeValue();
        dmqrv.setCodeIndicateurSaisie(clientEntreprise.getNiveauCA());
        dtoResultatFinancierFrance.setChiffreAffaireBorne(dmqrv);

        if (StringUtils.isNotEmpty(clientEntreprise.getAnneeExercice())) {
            DateRange dateRange = new DateRange();
            try {
                GregorianCalendar gCalendar6 = new GregorianCalendar();
                gCalendar6.set(Integer.parseInt(clientEntreprise.getAnneeExercice()), 1, 1);
                XMLGregorianCalendar anneeExercice = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar6);
                dateRange.setStartDate(anneeExercice);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }

            dtoResultatFinancierFrance.setPeriodeConsideree(dateRange);
        }

        // résultat financier export
        List<DtoResultatFinancierAExport> resultatFinancierAExport = new ArrayList<DtoResultatFinancierAExport>();
        DtoResultatFinancierAExport dtoResultatFinancierAExport = new DtoResultatFinancierAExport();
        DatedMonetaryQuantityRangeValue dmqrvPMAExport = new DatedMonetaryQuantityRangeValue();
        dmqrvPMAExport.setCodeIndicateurSaisie(clientEntreprise.getPartCAExport());
        dtoResultatFinancierAExport.setChiffreAffaireAExportBorne(dmqrvPMAExport);

        if (StringUtils.isNotEmpty(clientEntreprise.getAnneeExercice())) {
            dtoResultatFinancierAExport
                            .setAnnee(BigInteger.valueOf(Long.parseLong(clientEntreprise.getAnneeExercice())));
        }

        resultatFinancierAExport.add(dtoResultatFinancierAExport);
        dtoPersonneMorale.getResultatFinancierAExport().addAll(resultatFinancierAExport);

        resultatFinancier.add(dtoResultatFinancierFrance);
        dtoPersonneMorale.getResultatFinancier().addAll(resultatFinancier);

        DtoSuiviAnnuelEntreprise dtoSuiviAnnuelEntreprise = new DtoSuiviAnnuelEntreprise();
        if (StringUtils.isNotEmpty(clientEntreprise.getNbSalaries())) {
            DatedQuantityRangeValue dmqNbSalaries = new DatedQuantityRangeValue();
            dmqNbSalaries.setCodeIndicateurSaisie(clientEntreprise.getNbSalaries());
            dtoSuiviAnnuelEntreprise.setNombreEmployesBorne(dmqNbSalaries);

            // dtoSuiviAnnuelEntreprise.setNombreEmployes(BigInteger.valueOf(Long.parseLong(clientEntreprise
            // .getNbSalaries())));
        }
        if (StringUtils.isNotEmpty(clientEntreprise.getAnneeExercice())) {
            dtoSuiviAnnuelEntreprise
                            .setExercice(BigInteger.valueOf(Long.parseLong(clientEntreprise.getAnneeExercice())));
        }
        if (StringUtils.isNotEmpty(clientEntreprise.getNbCadres())) {
            DatedQuantityRangeValue dmqNbCadres = new DatedQuantityRangeValue();
            dmqNbCadres.setCodeIndicateurSaisie(clientEntreprise.getNbCadres());
            dtoSuiviAnnuelEntreprise.setNombreCadresBorne(dmqNbCadres);

            dtoSuiviAnnuelEntreprise
                            .setNombreCadres(BigInteger.valueOf(Long.parseLong(clientEntreprise.getNbCadres())));
        }
        List<DtoSuiviAnnuelEntreprise> listeSAE = new ArrayList<DtoSuiviAnnuelEntreprise>();
        listeSAE.add(dtoSuiviAnnuelEntreprise);
        dtoPersonneMorale.getSuiviAnnuelEntreprise().addAll(listeSAE);
        // }

        if (clientEntreprise.getDateCreationEntreprise() != null) {
            try {
                GregorianCalendar gCalendar4 = new GregorianCalendar();
                gCalendar4.setTime(clientEntreprise.getDateCreationEntreprise());
                XMLGregorianCalendar xmlCalendar4 = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar4);
                dtoPersonneMorale.setDateEtablissement(xmlCalendar4);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }
        }

        DtoEntreprise dtoEntreprise = new DtoEntreprise();
        dtoEntreprise.setCodeNIC(clientEntreprise.getCodeNic());
        dtoEntreprise.setCodeSIREN(clientEntreprise.getSiren());
        dtoEntreprise.setCaisseRetraite(clientEntreprise.getCaisseRetraite());
        dtoPersonneMorale.setEntreprise(dtoEntreprise);

        return dtoPersonneMorale;
    }

    /**
     * @param dtoPersonneMorale la personne morale
     * @param clientCollectivite Collectivite
     * @return DtoPersonneMorale
     */
    public DtoPersonneMorale buildCollectivite(DtoPersonneMorale dtoPersonneMorale,
                    IClientCollectivite clientCollectivite) {
        // Critères concernant uniquement les Collectivites
        DtoCollectiviteLocale dtoCollectivite = new DtoCollectiviteLocale();

        DatedMonetaryQuantityRangeValue dmqInvestissement = new DatedMonetaryQuantityRangeValue();
        if (StringUtils.isNotEmpty(clientCollectivite.getBudgetInvestissement())) {
            dmqInvestissement.setCodeIndicateurSaisie(clientCollectivite.getBudgetInvestissement());
        }
        dtoCollectivite.setBudgetInvestissementBorne(dmqInvestissement);

        DatedMonetaryQuantityRangeValue dmqFonctionnement = new DatedMonetaryQuantityRangeValue();
        if (StringUtils.isNotEmpty(clientCollectivite.getBudgetFonctionnement())) {
            dmqFonctionnement.setCodeIndicateurSaisie(clientCollectivite.getBudgetFonctionnement());
        }
        dtoCollectivite.setBudgetFonctionnementBorne(dmqFonctionnement);

        DatedQuantityRangeValue dmqHabitants = new DatedQuantityRangeValue();
        if (StringUtils.isNotEmpty(clientCollectivite.getBudgetFonctionnement())) {
            dmqHabitants.setCodeIndicateurSaisie(clientCollectivite.getNbHabitants());
        }
        dtoCollectivite.setNombreHabitantsBorne(dmqHabitants);

        dtoPersonneMorale.setCollectiviteLocale(dtoCollectivite);

        return dtoPersonneMorale;
    }

    /**
     * @param dtoPersonneMorale la personne morale
     * @param clientCopropriete Copropriete
     * @return DtoPersonneMorale
     */
    public DtoPersonneMorale buildCopropriete(DtoPersonneMorale dtoPersonneMorale, IClientCopropriete clientCopropriete) {
        // Critères concernant uniquement les Coproprietes
        DtoCoPropriete dtoCopropriete = new DtoCoPropriete();
        dtoCopropriete.setIndicateurGardien(clientCopropriete.isGardien());
        dtoCopropriete.setIndicateurDigicode(clientCopropriete.isDigicode());
        dtoCopropriete.setIndicateurInterphone(clientCopropriete.isInterphone());
        dtoCopropriete.setAnneeConstruction(clientCopropriete.getAnneeConstruction());

        if (StringUtils.isNotEmpty(clientCopropriete.getSurfaceDeveloppee())) {
            dtoCopropriete.setSurfaceDeveloppee(Float.valueOf(clientCopropriete.getSurfaceDeveloppee()));
        }

        if (StringUtils.isNotEmpty(clientCopropriete.getNbLots())) {
            dtoCopropriete.setNombreLots(BigInteger.valueOf(Long.parseLong(clientCopropriete.getNbLots())));
        }

        dtoPersonneMorale.setCoPropriete(dtoCopropriete);

        return dtoPersonneMorale;
    }

    /**
     * @param dtoPersonneMorale la personne morale
     * @param clientAssociation Association
     * @return DtoPersonneMorale
     */
    public DtoPersonneMorale buildAssociation(DtoPersonneMorale dtoPersonneMorale, IClientAssociation clientAssociation) {
        // Critères concernant uniquement les Associations
        DtoAssociation dtoAssociation = new DtoAssociation();
        dtoAssociation.setTypeAssociation(clientAssociation.getType());
        dtoAssociation.setAssociationUtilitePublique(clientAssociation.isUtilitePublique());

        DatedMonetaryQuantityRangeValue dmqrvRevenuBorne = new DatedMonetaryQuantityRangeValue();
        if (StringUtils.isNotEmpty(clientAssociation.getBudgetAnnuel())) {
            dmqrvRevenuBorne.setCodeIndicateurSaisie(clientAssociation.getBudgetAnnuel());
        }
        dtoAssociation.setBudgetAnnuelBorne(dmqrvRevenuBorne);

        DatedQuantityRangeValue dmqrvNbAdherents = new DatedQuantityRangeValue();
        if (StringUtils.isNotEmpty(clientAssociation.getNbAdherents())) {
            dmqrvNbAdherents.setCodeIndicateurSaisie(clientAssociation.getNbAdherents());
        }
        dtoAssociation.setNombreDeMembresBorne(dmqrvNbAdherents);

        if (StringUtils.isNotEmpty(clientAssociation.getNbMembresActifs())) {
            dtoAssociation.setNombreMembresActifsDuBureau(BigInteger.valueOf(Long.parseLong(clientAssociation
                            .getNbMembresActifs())));
        }

        DatedQuantityRangeValue dmqrvBenevoles = new DatedQuantityRangeValue();
        if (StringUtils.isNotEmpty(clientAssociation.getNbBenevoles())) {
            dmqrvBenevoles.setCodeIndicateurSaisie(clientAssociation.getNbBenevoles());
        }
        dtoAssociation.setNombreBenevolesBorne(dmqrvBenevoles);

        dtoPersonneMorale.setAssociation(dtoAssociation);

        return dtoPersonneMorale;
    }

    /**
     * @param dtoPersonneMorale la personne morale
     * @param clientAutre Autre client
     * @return DtoPersonneMorale
     */
    public DtoPersonneMorale buildAutre(DtoPersonneMorale dtoPersonneMorale, IClientAutre clientAutre) {
        // Critères concernant uniquement les autres clients
        DtoExploitationAgricole dtoExploitationAgricole = new DtoExploitationAgricole();
        DatedQuantity datedQuantity = new DatedQuantity();
        if (StringUtils.isNotEmpty(clientAutre.getSurfaceCultivable())) {
            datedQuantity.setValue(BigDecimal.valueOf(Long.parseLong(clientAutre.getSurfaceCultivable())));
        }
        dtoExploitationAgricole.setSurfaceCultivable(datedQuantity);
        dtoPersonneMorale.setDetailActivitePersonneMorale(dtoExploitationAgricole);

        if (clientAutre.getDateCreationPM() != null) {
            try {
                GregorianCalendar gCalendar4 = new GregorianCalendar();
                gCalendar4.setTime(clientAutre.getDateCreationPM());
                XMLGregorianCalendar xmlCalendar4 = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar4);
                dtoPersonneMorale.setDateEtablissement(xmlCalendar4);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }
        }

        return dtoPersonneMorale;
    }

}
